【Golang零基础入门】07 Channel

channel 是goroutine的通道,所以不能直接在非goroutine里直接进行操作,否则会报错,例如

1
2
3
4
c := make(chan int)
c <- 1

fatal error: all goroutines are asleep - deadlock!

var i chan int // 双向channel

var i chan<- int // 单向,只能收数据
i <- 1 // 这是允许的
j <- i // 这是不允许的

var i <-chan int // 单向,只能发数据

buffer channel

buffer可以减少goroutine的切换,例如下面,创建了3buffer的channel,在往channel写数据时,前3个写入都是会存储到buffer,但是写第4个的时候,会发现报错,fatal error: all goroutines are asleep - deadlock!,因为buffer已满,没有goroutine处理该channel数据。所以如果是没有buffer的channel,每次写入都会有一次goroutine的切换。

1
2
3
4
5
6
7
func bufferChannel()  {
c := make(chan int, 3) // 创建带有3 buffer的channel
c <- 'a'
c <- 'b'
c <- 'c'
//c <- 'd' // 取消注释后会报错,因为没有接受处理channel的方法
}

channel close

1
2
3
4
5
6
7
8
9
10
11
12
13
14
func worker(c chan int) {
for n := range c {
fmt.Printf("received %c\n", n)
}
}

func closeDemo() {
c := make(chan int, 3)
go worker(c)
c <- 'a'
c <- 'b'
c <- 'c'
close(c) // 主动关闭channel,如果不主动关闭,goroutine会一直收数据
}

不要通过共享内存来通信,通过通信来共享内存

这篇文章里面说的比较清楚了,使用共享内存的话在多线程的场景下为了处理竞态,需要加锁,使用起来比较麻烦。另外使用过多的锁,容易使得程序的代码逻辑坚涩难懂,并且容易使程序死锁,死锁了以后排查问题相当困难,特别是很多锁同时存在的时候。

go语言的channel保证同一个时间只有一个goroutine能够访问里面的数据,为开发者提供了一种优雅简单的工具,所以go原生的做法就是使用channle来通信,而不是使用共享内存来通信。

http://legendtkl.com/2017/07/30/understanding-golang-channel/

本文标题:【Golang零基础入门】07 Channel

文章作者:Craze lee

发布时间:2019年05月18日 - 11:05

最后更新:2019年05月20日 - 10:05

原始链接:http://craze-lee.github.io/2019/05/18/Golang/零基础入门/07 Channel/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

您的支持将鼓励我继续创作!